package com.pinfly.common.crypto.ui;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.ButtonGroup;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

import com.pinfly.common.crypto.CryptoFactory;
import com.pinfly.common.crypto.ICrypto;
import com.pinfly.common.util.HexConvert;

/**
 * This provides a UI for encrypting text using the Pinfly CryptoFactory and
 * implementation.
 * 
 */
public class CryptoTool extends JFrame implements ActionListener
{

    private static final String s_title = "Pinfly Crypto Tool";
    private static final int WINDOW_WIDTH = 500;
    private static final int WINDOW_HEIGHT = 410;

    private static final String CMD_ENCRYPT = "encrypt";
    private static final String CMD_CLEAR = "clear";
    private static final String CMD_EXIT = "exit";
    private static final String CMD_ABOUT = "about";
    private static final String CMD_DEFAULT_KEY = "default";
    private static final String CMD_CUST_KEY = "cust";

    private Container m_cp;

    private javax.swing.JButton bEncrypt;
    private javax.swing.JButton bClear;
    private javax.swing.JLabel lKeyText;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JRadioButton rbDefault;
    private javax.swing.JRadioButton rbKeyText;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea taEncryptedData;
    private javax.swing.JTextField tfKeyText;
    private javax.swing.JTextField tfPlainText;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private ButtonGroup m_group = new ButtonGroup ();

    private JDialog aboutBox;

    private CryptoTool ()
    {
        super (s_title);
        setSize (WINDOW_WIDTH, WINDOW_HEIGHT);
        setResizable (false);

        initComponents ();
        this.setLocationRelativeTo (getRootPane ());
    }

    private void initComponents ()
    {
        m_cp = getContentPane ();

        mainPanel = new javax.swing.JPanel ();
        jPanel4 = new javax.swing.JPanel ();
        rbDefault = new javax.swing.JRadioButton ();
        rbDefault.setActionCommand (CMD_DEFAULT_KEY);
        rbDefault.addActionListener (this);
        rbDefault.setSelected (true);
        rbKeyText = new javax.swing.JRadioButton ();
        rbKeyText.setActionCommand (CMD_CUST_KEY);
        rbKeyText.addActionListener (this);
        m_group.add (rbDefault);
        m_group.add (rbKeyText);
        lKeyText = new javax.swing.JLabel ();
        lKeyText.setVisible (false);
        tfKeyText = new javax.swing.JTextField ();
        tfKeyText.setVisible (false);
        jPanel1 = new javax.swing.JPanel ();
        tfPlainText = new javax.swing.JTextField ();
        jPanel2 = new javax.swing.JPanel ();
        jScrollPane1 = new javax.swing.JScrollPane ();
        taEncryptedData = new javax.swing.JTextArea ();
        bEncrypt = new javax.swing.JButton ();
        bClear = new javax.swing.JButton ();
        menuBar = new javax.swing.JMenuBar ();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu ();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem ();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu ();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem ();

        mainPanel.setName ("mainPanel");

        jPanel4.setBorder (javax.swing.BorderFactory.createTitledBorder ("Key Selection"));

        rbDefault.setText ("Default Key");

        rbKeyText.setText ("Custom Key");

        lKeyText.setText ("Key Text");

        tfKeyText.setText ("");

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout (jPanel4);
        jPanel4.setLayout (jPanel4Layout);
        jPanel4Layout.setHorizontalGroup (jPanel4Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                       .addGroup (jPanel4Layout.createSequentialGroup ()
                                                                               .addContainerGap ()
                                                                               .addGroup (jPanel4Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                                                                       .addComponent (rbDefault)
                                                                                                       .addGroup (jPanel4Layout.createSequentialGroup ()
                                                                                                                               .addGap (55,
                                                                                                                                        55,
                                                                                                                                        55)
                                                                                                                               .addComponent (lKeyText)
                                                                                                                               .addPreferredGap (javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                                                                                                               .addComponent (tfKeyText,
                                                                                                                                              javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                                                              312,
                                                                                                                                              javax.swing.GroupLayout.PREFERRED_SIZE))
                                                                                                       .addComponent (rbKeyText))
                                                                               .addContainerGap (javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                 Short.MAX_VALUE)));
        jPanel4Layout.setVerticalGroup (jPanel4Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                     .addGroup (jPanel4Layout.createSequentialGroup ()
                                                                             .addComponent (rbDefault)
                                                                             .addPreferredGap (javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                                             .addComponent (rbKeyText)
                                                                             .addPreferredGap (javax.swing.LayoutStyle.ComponentPlacement.RELATED,
                                                                                               javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                               Short.MAX_VALUE)
                                                                             .addGroup (jPanel4Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.BASELINE)
                                                                                                     .addComponent (tfKeyText,
                                                                                                                    javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                                    javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                    javax.swing.GroupLayout.PREFERRED_SIZE)
                                                                                                     .addComponent (lKeyText))
                                                                             .addContainerGap ()));

        jPanel1.setBorder (javax.swing.BorderFactory.createTitledBorder ("Text To Encrypt"));

        tfPlainText.setText ("");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout (jPanel1);
        jPanel1.setLayout (jPanel1Layout);
        jPanel1Layout.setHorizontalGroup (jPanel1Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                       .addGroup (jPanel1Layout.createSequentialGroup ()
                                                                               .addContainerGap ()
                                                                               .addComponent (tfPlainText,
                                                                                              javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                              430,
                                                                                              javax.swing.GroupLayout.PREFERRED_SIZE)
                                                                               .addContainerGap (13, Short.MAX_VALUE)));
        jPanel1Layout.setVerticalGroup (jPanel1Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                     .addGroup (jPanel1Layout.createSequentialGroup ()
                                                                             .addComponent (tfPlainText,
                                                                                            javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                            javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                            javax.swing.GroupLayout.PREFERRED_SIZE)
                                                                             .addContainerGap (javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                               Short.MAX_VALUE)));

        jPanel2.setBorder (javax.swing.BorderFactory.createTitledBorder ("Encrypted Data"));

        jScrollPane1.setName ("jScrollPane1");

        taEncryptedData.setColumns (20);
        taEncryptedData.setRows (5);
        taEncryptedData.setLineWrap (true);
        jScrollPane1.setViewportView (taEncryptedData);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout (jPanel2);
        jPanel2.setLayout (jPanel2Layout);
        jPanel2Layout.setHorizontalGroup (jPanel2Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                       .addGroup (jPanel2Layout.createSequentialGroup ()
                                                                               .addContainerGap ()
                                                                               .addComponent (jScrollPane1,
                                                                                              javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                              433, Short.MAX_VALUE)
                                                                               .addContainerGap ()));
        jPanel2Layout.setVerticalGroup (jPanel2Layout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                     .addGroup (jPanel2Layout.createSequentialGroup ()
                                                                             .addComponent (jScrollPane1,
                                                                                            javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                            86, Short.MAX_VALUE)
                                                                             .addContainerGap ()));

        bEncrypt.setText ("Encrypt");
        bEncrypt.setActionCommand (CMD_ENCRYPT);
        bEncrypt.addActionListener (this);

        bClear.setText ("Clear");
        bClear.setActionCommand (CMD_CLEAR);
        bClear.addActionListener (this);

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout (mainPanel);
        mainPanel.setLayout (mainPanelLayout);
        mainPanelLayout.setHorizontalGroup (mainPanelLayout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                           .addGroup (mainPanelLayout.createSequentialGroup ()
                                                                                     .addContainerGap ()
                                                                                     .addGroup (mainPanelLayout.createParallelGroup (javax.swing.GroupLayout.Alignment.TRAILING)
                                                                                                               .addComponent (jPanel2,
                                                                                                                              javax.swing.GroupLayout.Alignment.LEADING,
                                                                                                                              javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                              javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                              Short.MAX_VALUE)
                                                                                                               .addGroup (javax.swing.GroupLayout.Alignment.LEADING,
                                                                                                                          mainPanelLayout.createParallelGroup (javax.swing.GroupLayout.Alignment.TRAILING,
                                                                                                                                                               false)
                                                                                                                                         .addGroup (javax.swing.GroupLayout.Alignment.LEADING,
                                                                                                                                                    mainPanelLayout.createSequentialGroup ()
                                                                                                                                                                   .addComponent (bEncrypt)
                                                                                                                                                                   .addPreferredGap (javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                                                                                                                                   .addComponent (bClear))
                                                                                                                                         .addComponent (jPanel1,
                                                                                                                                                        javax.swing.GroupLayout.Alignment.LEADING,
                                                                                                                                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                                                        Short.MAX_VALUE)
                                                                                                                                         .addComponent (jPanel4,
                                                                                                                                                        javax.swing.GroupLayout.Alignment.LEADING,
                                                                                                                                                        javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                                                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                                                        javax.swing.GroupLayout.PREFERRED_SIZE)))
                                                                                     .addContainerGap (javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                       Short.MAX_VALUE)));
        mainPanelLayout.setVerticalGroup (mainPanelLayout.createParallelGroup (javax.swing.GroupLayout.Alignment.LEADING)
                                                         .addGroup (mainPanelLayout.createSequentialGroup ()
                                                                                   .addContainerGap ()
                                                                                   .addComponent (jPanel4,
                                                                                                  javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                  javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                  javax.swing.GroupLayout.PREFERRED_SIZE)
                                                                                   .addPreferredGap (javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                                                                   .addComponent (jPanel1,
                                                                                                  javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                  javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                  javax.swing.GroupLayout.PREFERRED_SIZE)
                                                                                   .addPreferredGap (javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                                                   .addGroup (mainPanelLayout.createParallelGroup (javax.swing.GroupLayout.Alignment.BASELINE)
                                                                                                             .addComponent (bEncrypt)
                                                                                                             .addComponent (bClear))
                                                                                   .addPreferredGap (javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                                                   .addComponent (jPanel2,
                                                                                                  javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                  javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                  Short.MAX_VALUE)
                                                                                   .addContainerGap ()));

        fileMenu.setText ("File");

        exitMenuItem.setText ("Exit");
        exitMenuItem.setActionCommand (CMD_EXIT);
        exitMenuItem.addActionListener (this);
        fileMenu.add (exitMenuItem);

        menuBar.add (fileMenu);

        helpMenu.setText ("Help");

        aboutMenuItem.setText ("About");
        aboutMenuItem.setActionCommand (CMD_ABOUT);
        aboutMenuItem.addActionListener (this);

        helpMenu.add (aboutMenuItem);

        menuBar.add (helpMenu);

        setJMenuBar (menuBar);

        m_cp.add (mainPanel);

    }

    /**
     * @param args
     */
    public static void main (String[] args)
    {
        String data = null;
        String keyText = null;
        String hexData = null;

        // args can override property file
        for (int i = 0; i < args.length; ++i)
        {
            if (args[i].equalsIgnoreCase ("-data") || args[i].equalsIgnoreCase ("/data"))
            {
                data = args[++i];
            }
            else if (args[i].equalsIgnoreCase ("-key") || args[i].equalsIgnoreCase ("/key"))
            {
                keyText = args[++i];
            }
            else if (args[i].equalsIgnoreCase ("-hex") || args[i].equalsIgnoreCase ("/hex"))
            {
                hexData = args[++i];
            }
        }

        // If hex is not null, we need to convert the hex string
        // back to a string and replace the data. The hex command line
        // argument is used because if the data that is being send in has
        // a ! in it the windows shell needs to have this escaped with a
        // ^. So the caller, probably the Java installshield, can convert
        // the data to a hexstring using code similar to the HexConvert class
        // in core and pass the data in as a hex string. This class will convert
        // the data back to its original string and then encrypt it.

        if (hexData != null)
        {
            data = new String (HexConvert.convertToBytes (hexData));
        }

        if (data != null)
        {
            try
            {
                ICrypto crypto = null;
                if (keyText != null)
                {
                    crypto = CryptoFactory.getInstance (keyText);
                }
                else
                {
                    crypto = CryptoFactory.getInstance ();
                }

                String enc = crypto.encrypt (data);
                System.out.println (enc);
                System.exit (0);
            }
            catch (Exception e)
            {
                e.printStackTrace ();
            }
        }
        else
        {
            final CryptoTool ui = new CryptoTool ();
            ui.addWindowListener (new WindowAdapter ()
            {
                public void windowClosing (WindowEvent e)
                {

                    System.exit (0);
                }
            });
            ui.setVisible (true);
        }

    }

    private void showMessage (String msg)
    {
        JOptionPane.showMessageDialog (this, msg);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed (ActionEvent e)
    {
        String cmd = e.getActionCommand ();

        if (CMD_ENCRYPT.equals (cmd))
        {
            taEncryptedData.setText ("");

            try
            {
                if (tfPlainText.getText ().isEmpty ())
                {
                    showMessage ("Please enter data in the Text To Encrypt field");
                    return;
                }

                ICrypto crypto = null;
                if (rbDefault.isSelected ())
                {
                    crypto = CryptoFactory.getInstance ();
                    String enc = crypto.encrypt (tfPlainText.getText ());
                    taEncryptedData.setText (enc);
                }
                else
                {
                    if (tfKeyText.getText ().isEmpty ())
                    {
                        showMessage ("Please enter data in the Key Text field");
                        return;
                    }
                    else
                    {
                        String keyText = tfKeyText.getText ();
                        crypto = CryptoFactory.getInstance (keyText);
                        String enc = crypto.encrypt (tfPlainText.getText ());
                        taEncryptedData.setText (enc);
                    }
                }

            }
            catch (Exception ex)
            {
                showMessage ("Error: " + ex.getMessage ());
            }
        }
        else if (CMD_CLEAR.equals (cmd))
        {
            taEncryptedData.setText ("");
        }
        else if (CMD_EXIT.equals (cmd))
        {
            System.exit (0);
        }
        else if (CMD_ABOUT.equals (cmd))
        {
            if (aboutBox == null)
            {
                aboutBox = new CryptoToolAboutBox (this);
                aboutBox.setLocationRelativeTo (this);

            }
            aboutBox.setVisible (true);
        }
        else if (CMD_DEFAULT_KEY.equals (cmd))
        {
            lKeyText.setVisible (false);
            tfKeyText.setVisible (false);
        }
        else if (CMD_CUST_KEY.equals (cmd))
        {
            lKeyText.setVisible (true);
            tfKeyText.setVisible (true);
        }
    }

}
